/**
 * 微信小程序工具类
 */

/**
 * 格式化时间
 * @param {Date} date 日期对象
 * @param {string} format 格式化字符串，默认 'YYYY-MM-DD HH:mm:ss'
 * @returns {string} 格式化后的时间字符串
 */
function formatTime(date, format = 'YYYY-MM-DD HH:mm:ss') {
  if (!date) return ''
  
  if (typeof date === 'string' || typeof date === 'number') {
    date = new Date(date)
  }
  
  if (!(date instanceof Date) || isNaN(date.getTime())) {
    return ''
  }
  
  const year = date.getFullYear()
  const month = date.getMonth() + 1
  const day = date.getDate()
  const hour = date.getHours()
  const minute = date.getMinutes()
  const second = date.getSeconds()
  
  return format
    .replace('YYYY', year)
    .replace('MM', month.toString().padStart(2, '0'))
    .replace('DD', day.toString().padStart(2, '0'))
    .replace('HH', hour.toString().padStart(2, '0'))
    .replace('mm', minute.toString().padStart(2, '0'))
    .replace('ss', second.toString().padStart(2, '0'))
}

/**
 * 获取相对时间
 * @param {Date|string|number} date 日期
 * @returns {string} 相对时间字符串
 */
function getRelativeTime(date) {
  if (!date) return ''
  
  if (typeof date === 'string' || typeof date === 'number') {
    date = new Date(date)
  }
  
  if (!(date instanceof Date) || isNaN(date.getTime())) {
    return ''
  }
  
  const now = new Date()
  const diff = now.getTime() - date.getTime()
  const seconds = Math.floor(diff / 1000)
  const minutes = Math.floor(seconds / 60)
  const hours = Math.floor(minutes / 60)
  const days = Math.floor(hours / 24)
  
  if (seconds < 60) {
    return '刚刚'
  } else if (minutes < 60) {
    return `${minutes}分钟前`
  } else if (hours < 24) {
    return `${hours}小时前`
  } else if (days < 7) {
    return `${days}天前`
  } else {
    return formatTime(date, 'MM-DD')
  }
}

/**
 * 防抖函数
 * @param {Function} func 要防抖的函数
 * @param {number} wait 等待时间（毫秒）
 * @param {boolean} immediate 是否立即执行
 * @returns {Function} 防抖后的函数
 */
function debounce(func, wait, immediate) {
  let timeout
  return function executedFunction(...args) {
    const later = () => {
      timeout = null
      if (!immediate) func.apply(this, args)
    }
    const callNow = immediate && !timeout
    clearTimeout(timeout)
    timeout = setTimeout(later, wait)
    if (callNow) func.apply(this, args)
  }
}

/**
 * 节流函数
 * @param {Function} func 要节流的函数
 * @param {number} limit 时间间隔（毫秒）
 * @returns {Function} 节流后的函数
 */
function throttle(func, limit) {
  let inThrottle
  return function(...args) {
    if (!inThrottle) {
      func.apply(this, args)
      inThrottle = true
      setTimeout(() => inThrottle = false, limit)
    }
  }
}

/**
 * 深拷贝
 * @param {any} obj 要拷贝的对象
 * @returns {any} 拷贝后的对象
 */
function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') {
    return obj
  }
  
  if (obj instanceof Date) {
    return new Date(obj.getTime())
  }
  
  if (obj instanceof Array) {
    return obj.map(item => deepClone(item))
  }
  
  if (typeof obj === 'object') {
    const clonedObj = {}
    for (let key in obj) {
      if (obj.hasOwnProperty(key)) {
        clonedObj[key] = deepClone(obj[key])
      }
    }
    return clonedObj
  }
}

/**
 * 生成唯一ID
 * @param {number} length ID长度
 * @returns {string} 唯一ID
 */
function generateId(length = 8) {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
  let result = ''
  for (let i = 0; i < length; i++) {
    result += chars.charAt(Math.floor(Math.random() * chars.length))
  }
  return result
}

/**
 * 格式化文件大小
 * @param {number} bytes 字节数
 * @param {number} decimals 小数位数
 * @returns {string} 格式化后的文件大小
 */
function formatFileSize(bytes, decimals = 2) {
  if (bytes === 0) return '0 Bytes'
  
  const k = 1024
  const dm = decimals < 0 ? 0 : decimals
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
  
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  
  return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]
}

/**
 * 格式化数字
 * @param {number} num 数字
 * @returns {string} 格式化后的数字
 */
function formatNumber(num) {
  if (num < 1000) {
    return num.toString()
  } else if (num < 10000) {
    return (num / 1000).toFixed(1) + 'k'
  } else if (num < 100000000) {
    return (num / 10000).toFixed(1) + 'w'
  } else {
    return (num / 100000000).toFixed(1) + '亿'
  }
}

/**
 * 验证手机号
 * @param {string} phone 手机号
 * @returns {boolean} 是否有效
 */
function validatePhone(phone) {
  const phoneRegex = /^1[3-9]\d{9}$/
  return phoneRegex.test(phone)
}

/**
 * 验证邮箱
 * @param {string} email 邮箱
 * @returns {boolean} 是否有效
 */
function validateEmail(email) {
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
  return emailRegex.test(email)
}

/**
 * 验证身份证号
 * @param {string} idCard 身份证号
 * @returns {boolean} 是否有效
 */
function validateIdCard(idCard) {
  const idCardRegex = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
  return idCardRegex.test(idCard)
}

/**
 * 获取URL参数
 * @param {string} url URL字符串
 * @returns {object} 参数对象
 */
function getUrlParams(url) {
  const params = {}
  const urlObj = new URL(url)
  for (let [key, value] of urlObj.searchParams) {
    params[key] = value
  }
  return params
}

/**
 * 构建URL参数
 * @param {object} params 参数对象
 * @returns {string} URL参数字符串
 */
function buildUrlParams(params) {
  const searchParams = new URLSearchParams()
  for (let key in params) {
    if (params[key] !== null && params[key] !== undefined) {
      searchParams.append(key, params[key])
    }
  }
  return searchParams.toString()
}

/**
 * 存储数据到本地
 * @param {string} key 键名
 * @param {any} data 数据
 * @param {boolean} sync 是否同步存储
 */
function setStorage(key, data, sync = false) {
  try {
    if (sync) {
      wx.setStorageSync(key, data)
    } else {
      wx.setStorage({
        key,
        data
      })
    }
  } catch (error) {
    console.error('存储数据失败:', error)
  }
}

/**
 * 从本地获取数据
 * @param {string} key 键名
 * @param {boolean} sync 是否同步获取
 * @returns {any} 数据
 */
function getStorage(key, sync = false) {
  try {
    if (sync) {
      return wx.getStorageSync(key)
    } else {
      return new Promise((resolve, reject) => {
        wx.getStorage({
          key,
          success: res => resolve(res.data),
          fail: reject
        })
      })
    }
  } catch (error) {
    console.error('获取数据失败:', error)
    return sync ? null : Promise.resolve(null)
  }
}

/**
 * 删除本地数据
 * @param {string} key 键名
 * @param {boolean} sync 是否同步删除
 */
function removeStorage(key, sync = false) {
  try {
    if (sync) {
      wx.removeStorageSync(key)
    } else {
      wx.removeStorage({ key })
    }
  } catch (error) {
    console.error('删除数据失败:', error)
  }
}

/**
 * 清空本地数据
 * @param {boolean} sync 是否同步清空
 */
function clearStorage(sync = false) {
  try {
    if (sync) {
      wx.clearStorageSync()
    } else {
      wx.clearStorage()
    }
  } catch (error) {
    console.error('清空数据失败:', error)
  }
}

/**
 * 显示提示信息
 * @param {string} title 提示内容
 * @param {string} icon 图标类型
 * @param {number} duration 显示时长
 */
function showToast(title, icon = 'none', duration = 2000) {
  wx.showToast({
    title,
    icon,
    duration
  })
}

/**
 * 显示加载提示
 * @param {string} title 提示内容
 * @param {boolean} mask 是否显示透明蒙层
 */
function showLoading(title = '加载中...', mask = true) {
  wx.showLoading({
    title,
    mask
  })
}

/**
 * 隐藏加载提示
 */
function hideLoading() {
  wx.hideLoading()
}

/**
 * 显示模态对话框
 * @param {string} title 标题
 * @param {string} content 内容
 * @param {object} options 选项
 * @returns {Promise} Promise对象
 */
function showModal(title, content, options = {}) {
  return new Promise((resolve, reject) => {
    wx.showModal({
      title,
      content,
      showCancel: options.showCancel !== false,
      cancelText: options.cancelText || '取消',
      confirmText: options.confirmText || '确定',
      success: res => {
        if (res.confirm) {
          resolve(true)
        } else {
          resolve(false)
        }
      },
      fail: reject
    })
  })
}

/**
 * 页面跳转
 * @param {string} url 页面路径
 * @param {object} params 参数
 * @param {string} type 跳转类型
 */
function navigateTo(url, params = {}, type = 'navigateTo') {
  let fullUrl = url
  
  // 添加参数
  if (Object.keys(params).length > 0) {
    const paramStr = buildUrlParams(params)
    fullUrl += (url.includes('?') ? '&' : '?') + paramStr
  }
  
  // 根据类型跳转
  switch (type) {
    case 'redirectTo':
      wx.redirectTo({ url: fullUrl })
      break
    case 'reLaunch':
      wx.reLaunch({ url: fullUrl })
      break
    case 'switchTab':
      wx.switchTab({ url: fullUrl })
      break
    default:
      wx.navigateTo({ url: fullUrl })
  }
}

/**
 * 返回上一页
 * @param {number} delta 返回层数
 */
function navigateBack(delta = 1) {
  wx.navigateBack({ delta })
}

module.exports = {
  formatTime,
  getRelativeTime,
  debounce,
  throttle,
  deepClone,
  generateId,
  formatFileSize,
  formatNumber,
  validatePhone,
  validateEmail,
  validateIdCard,
  getUrlParams,
  buildUrlParams,
  setStorage,
  getStorage,
  removeStorage,
  clearStorage,
  showToast,
  showLoading,
  hideLoading,
  showModal,
  navigateTo,
  navigateBack
}